#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;


// —————————— lambda表达式 ————————
struct Goods
{
	string _name;  //名字
	double _price; // 价格
	int _evaluate; // 评价
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};

//仿函数比较
struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};

struct  ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price > gr._price;
	}
};


//int main(){
//	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,3 }, { "菠萝", 1.5, 4 } };
//	//价格升序
//	//sort(v.begin(), v.end(), ComparePriceLess());
//	//sort(v.begin(), v.end(), ComparePriceGreater());
//	
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
//		{
//			return g1._price < g2._price;
//		});
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
//		{
//			return g1._price > g2._price;
//		});
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
//		{
//			return g1._evaluate < g2._evaluate;
//		});
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
//		{
//			return g1._evaluate > g2._evaluate;
//		});
//
//}



// —————— lambda 匿名函数的对象 ————————
//int main()
//{
//	auto add1 = [](int x, int y)->int {return x + y; };
//	cout << add1(1, 2) << endl;
//
//	auto func1 = []()->int
//	{
//		cout << "hello bit" << endl;
//		cout << "hello world" << endl;
//		return 0;
//	};
//
//	func1();
//
//	// 返回值类型可自动推导类型，所以可以省略
//	// 无参数可以省略
//	// 返回值一般都不能省略
//	auto func2 = []
//	{
//		cout << "hello bit" << endl;
//		cout << "hello world" << endl;
//		return 0;
//	};
//
//	cout << func2() << endl;
//
//	//无返回值时可以省略返回值，但是建议最好还是有返回值
//	auto func3 = []
//	{
//		cout << "hello bit" << endl;
//		cout << "hello world" << endl;
//	};
//
//	func3();
//
//	return 0;
//}



//int main(){
//	int a = 0, b = 1;
//
//	auto swap1 = [](int& x, int& y){ //参数列表
//		// 只能用当前lambda局部域和捕捉的对象
//		int tmp = x;
//		x = y;
//		y = tmp;
//	};
//	swap1(a, b);
//
//	// 传值捕捉本质是一种拷贝,并且const修饰了
//	// mutable相当于去掉const属性，可以修改了
//	// 但是修改了不会影响外面被捕捉的值，因为是一种拷贝
//	auto swap2 = [a, b]()mutable{ //捕捉列表
//		int tmp = a;
//		a = b;
//		b = tmp;
//	};
//	swap2();
//
//	auto swap3 = [&a, &b](){ //这里 &是引用
//		int tmp = a;
//		a = b;
//		b = tmp;
//	};
//	swap3();
//
//	return 0;
//}



//int x = 0;
//int main(){
//	// 只能用当前lambda局部域和捕捉的对象和全局对象
//	int a = 0, b = 1, c = 2, d = 3;
//	// 所有值传值捕捉
//	auto func1 = [=]{
//		int ret = a + b + c + d + x;
//		return ret;
//	};
//	func1();
//	cout << "auto func1 = [=]："<< a << " " << b << " "  << c << " " << d << endl;
//
//	// 所有值传引用捕捉
//	auto func2 = [&]{
//		a++, b++, c++, d++;
//		int ret = a + b + c + d;
//		return ret;
//	};
//	func2();
//	cout <<"auto func2 = [&]："<< a << " " << b << " " << c << " " << d << endl;
//	
//
//	// 混合捕捉
//	auto func3 = [&a, b]{
//		a++;
//		//b++; //由于b是传值捕捉，b就不能修改
//		int ret = a + b;
//		return ret;
//	};
//	func3();
//	cout<<"auto func3 = [&a, b]：" << a << " " << b << " " << c << " " << d << endl;
//	
//
//	// 混合捕捉
//	// 所有值以引用方式捕捉，d用传值捕捉
//	auto func4 = [&, d]{
//		a++,b++,c++;
//		//d++; //故d不能修改
//		int ret = a + b + c + d;
//	};
//	func4();
//	cout << "auto func4 = [&, d]：" << a << " " << b << " "  << c << " " << d << endl;
//
//
//	auto func5 = [=, &d](){
//		//a++, b++, c++; //a,b,c都不能修改
//		d++; 
//		int ret = a + b + c + d;
//	};
//	func5();
//	cout << "auto func5 = [=, &d]()：" << a << " " << b << " " << c << " " << d << endl;
//
//	auto func6 = [=, &d]() mutable {
//		a++, b++, c++, d++; //都可以修改，但是只有d对外面的值有影响
//		int ret = a + b + c + d;
//	};
//	func6();
//	cout << "auto func6 = [=, &d]() mutable：" << a << " " << b << " "<< c << " " << d << endl;
//	
//	return 0;
//}




//// ——————————lambda 匿名函数的对象————————
//class Rate
//{
//public:
//	Rate(double rate) : _rate(rate)
//	{}
//
//	double operator()(double money, int year)
//	{
//		return money * _rate * year;
//	}
//private:
//	double _rate;
//};
//
////捕捉列表的对象是成员变量存在lambad类对象中
////捕捉的本质是构造函数的初始化列表
//
//int main(){
//	// 函数对象
//	double rate = 0.015;
//	Rate r1(rate);
//	cout << r1(10000, 2) << endl;
//
//	// lambda
//	auto r2 = [rate](double monty, int year)->double
//	{
//		return monty * rate * year;
//	};
//
//	cout << r2(10000, 2) << endl;
//
//	int x = 1, y = 2;
//	auto r3 = [=](double monty, int year)->double
//	{
//		return monty * rate * year;
//	};
//	cout << r3(10000, 2) << endl;
//
//	return 0;
//}



// —————————— 包装器 ——————————
#include<functional>

int f(int a, int b){
	return a + b;
}

struct Functor{
public:
	int operator() (int a, int b){
		return a + b;
	}
};

class Plus
{
public:
	static int plusi(int a, int b){
		return a + b;
	}

	double plusd(double a, double b){
		return a + b;
	}
};


int main()
{
	// 包装可调用对象
	//function<int(int)> f1 = f; //类型不匹配会报错的
	function<int(int, int)> f1 = f; //实例化方式
	function<int(int, int)> f2 = Functor();
	function<int(int, int)> f3 = [](int a, int b) {return a + b; };

	cout << f1(1, 1) << endl;
	cout << f2(1, 1) << endl;
	cout << f3(1, 1) << endl;

	//由于成员函数的函数名受类域限制，因此下面我们需要指定函数名
	// 包装静态成员函数
	function<int(int, int)> f4 = &Plus::plusi;
	cout << f4(1, 1) << endl;

	// 包装非静态成员函数
	//非静态的成员函数要取函数指针的时候，需要加个&，静态可以不加
	//function<double(double, double)> f5 = &Plus::plusd;  
	
	//由于上面编译通过，因为其还有一个隐含的this参数，下面有两种解决方案
	//方法一：传指针
	function<double(Plus*, double, double)> f5 = &Plus::plusd;
	Plus pd;
	cout << f5(&pd, 1.1, 1.1) << endl;

	//方法二：不传指针，只传对象
	function<double(Plus, double, double)> f6 = &Plus::plusd;
	cout << f6(pd, 1.1, 1.1) << endl;
	cout << f6(Plus(), 1.1, 1.1) << endl;

	return 0;
}



// —————————— bind ——————
int Sub(int a, int b){return (a - b) * 10;}

int SubX(int a, int b, int c){return (a - b - c) * 10;}

//可以用命名空间展示出来
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;

int main()
{
	//auto sub1 = bind(Sub,placeholders::_1,placeholders::_2);
	// bind 本质返回的一个仿函数对象
	// 调整参数顺序（不常用）
	// _1代表第一个实参
	// _2代表第二个实参

	auto sub1 = bind(Sub, _1, _2); //代表Sub(_1, _2)
	cout << sub1(10, 5) << endl;//10 相当于_1, 5相当于_2

	auto sub2 = bind(Sub, _2, _1); //代表Sub(_2, _1)
	cout << sub2(10, 5) << endl; //5 相当于_2, 10相当于_1

	//调整参数个数（常用）
	auto sub3 = bind(Sub, 10, _1); //代表Sub(100, _1)
	cout << sub3(5) << endl; //5 相当于_1

	auto sub4 = bind(Sub, _1, 10); //代表Sub(_1, 10)
	cout << sub4(5) << endl; //5 相当于_1

	// 分别绑死第123个参数
	auto sub5 = bind(SubX, 10, _1, _2);
	cout << sub5(5, 1) << endl;

	auto sub6 = bind(SubX, _1, 10, _2);
	cout << sub6(5, 1) << endl;

	auto sub7 = bind(SubX, _1, _2, 10);
	cout << sub7(5, 1) << endl;

	function<double(Plus, double, double)> f6 = &Plus::plusd;
	Plus pd;
	cout << f6(pd, 1.1, 1.1) << endl;
	cout << f6(Plus(), 1.1, 1.1) << endl;

	// bind一般用于，绑死一些固定参数
	function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);
	cout << f7(1.1, 1.1) << endl;


	//auto func1 = [](double rate, double money, int year)->double {return monty * rate * year; }; //单利
	auto func1 = [](double rate, double money, int year)->double { //复利
		double ret = money;
		for (int i = 0; i < year; i++)
		{
			ret += ret * rate;
		}

		return ret - money;
		};

	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
	function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);
	function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);
	function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);

	cout << func3_1_5(1000000) << endl;
	cout << func5_1_5(1000000) << endl;
	cout << func10_2_5(1000000) << endl;
	cout << func20_3_5(1000000) << endl;

	return 0;
}